#include "SkillBase.h"
#include "Character/SkillPart.h"
#include "base/core/log.h"
#include <list>
#include "Scene/Path.h"
#include "SkillMgr.h"
#include "Character/Creature.h"
#include "base/core/Profiler.h"
SkillBase::SkillBase()
{
	m_nID = 0;
	m_curState = SkillState_empty;
	m_targetPos = { -1, -1, -1 };
	m_curDamageCount = 0;

	m_vTargetCids.clear();

	m_nStep = 0;  //技能连招阶段
	m_nStopStep = 0;	//打断连招阶段
	m_vSkillId.clear();	//连招技能ID数组
	//m_posSummon = Point3<float>();
}
SkillBase::~SkillBase()
{
	refreshData();
}
void SkillBase::refreshData()
{
	m_pPart->KillTimedo(m_nGlobelID);
	m_nID = 0;
	m_curState = SkillState_empty;
	m_targetPos = { -1, -1, -1 };
	m_curDamageCount = 0;

	m_vTargetCids.clear();

	m_nStep=0;  //技能连招阶段
	m_nStopStep=0;	//打断连招阶段
	m_vSkillId.clear();	//连招技能ID数组
	//m_posSummon = Point3<float>();
}


bool SkillBase::Init(SkillFightType type, const SkillCfg* pConfig, uint32_t globelID, SkillPart * pPart)
{
	MMOLOG_PROCESS_ERROR(pConfig &&  pPart);
	m_enType = type;
	m_nID = pConfig->skillID;
	m_nGlobelID = globelID;
	m_pPart = pPart;
	m_nStep = 1;
	m_vSkillId.push_back(pConfig->skillID);

	while (pConfig && pConfig->relationSkillId > 0)
	{
		m_vSkillId.push_back(pConfig->relationSkillId);
		pConfig = g_GetSkillMgr()->GetSkillCfg(pConfig->relationSkillId);
	}
	m_nStopStep = m_vSkillId.size();
	m_masterPos = m_pPart->GetMasterPos();
	m_focoTime = 0;
	m_mapTimedofunc.insert(make_pair(SkillState_ready, &SkillBase::OnReadyTimedo));
	m_mapTimedofunc.insert(make_pair(SkillState_Fly, &SkillBase::OnFly));
	m_mapTimedofunc.insert(make_pair(SkillState_damage,&SkillBase::OnDamageTimedo));
	m_mapTimedofunc.insert(make_pair(SkillState_NextSkill,&SkillBase::OnNextSkillStatedo));

	return true;
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
	return true;
}

//根据起点，方向，间隔时间，算出目标应在的终点坐标和方向
void SkillBase::GetDesPos(Point3<float> startPos, Point3<float> startDir, uint32_t nSpeed, Point3<float> & desPos, uint32_t intervalTime)
{
	if (intervalTime <= 0)
		return;

	//Path tmpPath;
	//VEC_POINT3 vPath;
	//vPath.push_back(desPos);
	//tmpPath.Init(vPath, startPos);

	//float moveDistance = nSpeed * intervalTime / 1000.0f;

	//tmpPath.MapPathDistanceToPoint(moveDistance, desPos);


	//根据开始位置和方向，距离，算出目标点坐标
	float moveDistance = nSpeed * intervalTime / 1000.0f;

	//算出方向单位向量
	Point3<float> tmpDir = Point3<float>(startDir.x / startDir.length(), startDir.y / startDir.length(), startDir.z / startDir.length());

	desPos = startPos + moveDistance*tmpDir;

	return;
}

uint32_t SkillBase::GetSkillID()
{
	return m_nID;
}

uint32_t SkillBase::GetDamageTime()
{
	return m_curDamageCount;
}

uint32_t SkillBase::GetFocoTime()
{
	return m_focoTime;
}


bool SkillBase::IsSameSkill(uint32_t skillID)
{
	VEC_UINT32::iterator iter = find(m_vSkillId.begin(), m_vSkillId.end(), skillID);
	if (iter==m_vSkillId.end())
	{
		return false;
	}

	return true;
}

uint32_t SkillBase::GetGlobelID()
{
	return m_nGlobelID;
}


void SkillBase::SetTargetPos(Point3<float> targetPos)
{
	m_targetPos = targetPos;
}
Point3<float> & SkillBase::GetTargetPos()
{
	return m_targetPos;
}

void SkillBase::SetTargetCidsList(vector<CharIDType> vtargetList)
{
	m_vTargetCids.clear();
	for (int i = 0; i < (int)vtargetList.size();++i)
	{
		m_vTargetCids.push_back(vtargetList[i]);
	}
}
vector<CharIDType> & SkillBase::GetTargetList()
{
	return m_vTargetCids;
}


void SkillBase::ReadyState(uint32_t skillId)
{
	stSkillInfo* pSkill = m_pPart->GetSkillInfo(skillId);
	MMOLOG_PROCESS_ERROR(pSkill);

	//cd时间定时
	//uint32_t cdTimeId = cdTimeIdPre + skillId;
	pSkill->_cdTimeStamps = Time::Now().UnixMSec();  // + pSkill->_pSkillmeta->cd;
	//m_pPart->SetTimedo(cdTimeId, pSkill->_pSkillmeta->cd, 1);

	//LogDebugFmtPrint("skill readytime begin, skillId:%d", skillId);
	if (pSkill->_pSkillmeta->readyTime <= 0)
	{
		DamageState(skillId);
		return;
	}
	else
	{
		m_curState = SkillState_ready;
		m_pPart->SetTimedo(m_nGlobelID, pSkill->_pSkillmeta->readyTime, 1);
	}

	return;
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
}

void SkillBase::DamageState(uint32_t skillId)
{
	stSkillInfo* pSkill = m_pPart->GetSkillInfo(skillId);
	MMOLOG_PROCESS_ERROR(pSkill);
	m_pPart->KillTimedo(m_nGlobelID);
	m_curState = SkillState_damage;

	//LogDebugFmtPrint("skill ready timeover, damagetime begin, damgeCount:%d, skillId:%d",pSkill->pSkillmeta->damageTime.size(), skillId);
	if (pSkill->_pSkillmeta->damageTime.empty())
	{
		LogDebugFmtPrint("skillid=%d,damagetime is empty", skillId);
		OnDamageTimedo(skillId);
	}
	else
	{
		//LogDebugFmtPrint("skillid=%d,damagetime=%d", skillId, pSkill->_pSkillmeta->damageTime[0]);
		if (pSkill->_pSkillmeta->damageTime[0]<=0)
		{
			//LogErrFmtPrint("skillid=%d, damagetime =%d error", skillId,pSkill->_pSkillmeta->damageTime[0]);
			OnDamageTimedo(skillId);
		}
		else
		{
			m_pPart->SetTimedo(m_nGlobelID, pSkill->_pSkillmeta->damageTime[0],1);
		}
	}
	return;
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
}

void SkillBase::OnDamageTimedoPlayer(uint32_t skillId, cList & vtargetList)
{
	//BEGIN_PROFILE("SkillBase::OnDamageTimedo");
	cList  targetCidList;
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillId);
	MMOLOG_PROCESS_ERROR(pConfig);

	//m_pPart->KillTimedo(m_nGlobelID);
	//m_pPart->FindCreatures(pConfig, m_pPart->GetMasterPos(), m_skillDir, targetCid, m_targetPos, m_curDamageCount, m_focoTime, targetCidList);
	//计算技能结果
	m_pPart->SkillResult(skillId, pConfig, m_curDamageCount, m_focoTime, vtargetList);


	if ((uint32_t)pConfig->damageTime.size() > m_curDamageCount + 1)
	{
		m_curDamageCount++;
	}
	else
	{
		m_nStep++;
		if (m_nStep > m_nStopStep || m_nStep > m_vSkillId.size())
		{
			m_pPart->KillTimedo(m_nGlobelID);
			m_pPart->RemoveSkillFightInfo(m_nGlobelID);
		}
	}
	return;
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
}

void SkillBase::OnDamageTimedo(uint32_t skillId)
{
	CharIDType targetCid = 0;
	cList  targetCidList;
	std::vector<int32_t> DistanceOutPram;
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(skillId);
	MMOLOG_PROCESS_ERROR(pConfig);

	m_pPart->KillTimedo(m_nGlobelID);

	//根据时间点来取找当前目标
	if (Range_none_target > pConfig->rangeType)
	{
		MMOLOG_PROCESS_ERROR((uint32_t)m_vTargetCids.size() > 0);

		if (m_curDamageCount >= m_vTargetCids.size())
		{
			targetCid = m_vTargetCids[0];
		}
		else
		{
			targetCid = m_vTargetCids[m_curDamageCount];
		}
	}

	//LogDebugFmtPrint("skill damagetimeDo, curdamgeCount:%d, skillId:%d, targetCid:%d", pSkill->curDamageCount, skillId, targetCid);
	

	m_pPart->FindCreatures(pConfig, m_pPart->GetMasterPos(), m_skillDir, targetCid, m_targetPos, m_curDamageCount, m_focoTime, targetCidList);
	
	//计算技能结果
	m_pPart->SkillResult(skillId, pConfig, m_curDamageCount, m_focoTime, targetCidList);


	
	CommonApi::SplitStrToVecInt(pConfig->displaceDistance, ",", &DistanceOutPram);
	////先判断需不需要对释放者做位移操作
	if (DistanceOutPram.size() > m_curDamageCount)
	{
		//位移配置距离
		Point3<float> desPos = m_pPart->GetMasterPos() + m_skillDir*DistanceOutPram[m_curDamageCount] / 1000.0;
		m_pPart->GetMaster()->SetPos(desPos);
	}


	if ((uint32_t)pConfig->damageTime.size() >m_curDamageCount + 1)
	{
		m_curDamageCount++;
		m_pPart->SetTimedo(m_nGlobelID, pConfig->damageTime[m_curDamageCount], 1);
	}
	else
	{
		//LogDebugFmtPrint("skill damge done, skillId:%d", skillId);
		//refreshData();

		if (m_vSkillId.size()>1)
		{
			OnNextSkillState(skillId);
		}
		else
		{
			//技能一次释放完成，需要删通知删除
			m_pPart->RemoveSkillFightInfo(m_nGlobelID);
		}
	}
	return;
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
}

void SkillBase::OnNextSkillState(uint32_t skillId)
{
	m_nStep++;
	m_curState = SkillState_NextSkill;
	SkillReadyRsp rsp;
	const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(m_vSkillId[m_nStep - 1]);
	MMOLOG_PROCESS_ERROR(pConfig);
	MMOLOG_PROCESS_ERROR(m_nStep <= m_nStopStep && m_nStep <= m_vSkillId.size());

	//进这里现在只可能是怪物放技能，这里多段目标点都是以自身的范围
	m_curDamageCount = 0;
	m_focoTime = 0;
	m_targetPos.x = 0;
	m_targetPos.y = 0;
	m_targetPos.z = 0;
	//如果有预警，也需要发送提示预警
	if (pConfig->warn)
	{
		//下发预警消息
		rsp.set_skillid(m_vSkillId[m_nStep - 1]);
		rsp.set_usercid(m_pPart->GetMasterCid());
		ProtoBuf::Vector3PB *pTargetPos = new ProtoBuf::Vector3PB();
		pTargetPos->set_x(m_pPart->GetMasterPos().x);
		pTargetPos->set_y(m_targetPos.y);
		pTargetPos->set_z(m_targetPos.z);
		rsp.set_allocated_targetpos(pTargetPos);

		m_pPart->GetMaster()->BroadCastData(LOGIC_TO_CLIENT_SKILL_READY, &rsp);
	}



	if (pConfig->damageTime.size() > 0)
	{
		m_pPart->SetTimedo(m_nGlobelID, pConfig->damageTime[m_curDamageCount], 1);
	}
	else
		OnNextSkillStatedo(m_vSkillId[m_nStep - 1]);

	return;
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
}

void SkillBase::OnNextSkillStatedo(uint32_t skillId)
{
	cList  targetCidList;
	MMOLOG_PROCESS_ERROR(m_nStep <= m_nStopStep && m_nStep <= m_vSkillId.size());
	
	{
		//先计算这个技能伤害，发结果，判断有没打断消息，没有，再启一定时器，算下一个技能伤害，

		//stSkillInfo *pSkill  = m_pPart->GetSkillInfo(m_vSkillId[m_nStep-1]);
		const SkillCfg* pConfig = g_GetSkillMgr()->GetSkillCfg(m_vSkillId[m_nStep - 1]);
		MMOLOG_PROCESS_ERROR(pConfig);

		m_pPart->KillTimedo(m_nGlobelID);
		CharIDType targetCid = 0;

		//根据时间点来取找当前目标
		if (Range_none_target > pConfig->rangeType)
		{
			MMOLOG_PROCESS_ERROR(m_curDamageCount < m_vTargetCids.size());
			targetCid = m_vTargetCids[m_curDamageCount];
		}

		//LogDebugFmtPrint("skill damagetimeDo, curdamgeCount:%d, skillId:%d, targetCid:%d", pSkill->curDamageCount, skillId, targetCid);

		m_pPart->FindCreatures(pConfig, m_pPart->GetMasterPos(), m_pPart->GetMasterDir(), targetCid, m_targetPos, m_curDamageCount, m_focoTime, targetCidList);
		//计算技能结果
		m_pPart->SkillResult(m_vSkillId[0], pConfig, m_curDamageCount, m_focoTime, targetCidList);

		if (pConfig->damageTime.size() > m_curDamageCount + 1)
		{
			m_curDamageCount++;
			m_pPart->SetTimedo(m_nGlobelID, pConfig->damageTime[m_curDamageCount], 1);
		}
		else
		{
			//LogDebugFmtPrint("skill damge done, skillId:%d", skillId);

			OnNextSkillState(skillId);
		}
		return;
	}
Exit0:
	m_pPart->KillTimedo(m_nGlobelID);
	m_pPart->RemoveSkillFightInfo(m_nGlobelID);
}

void SkillBase::SetStopStep(uint32_t  step)
{
	m_nStopStep = step + 1;
}

void SkillBase::OnReadyTimedo(uint32_t skillId)
{
	DamageState(skillId);
}

void SkillBase::OnTime()
{
	mapTimedoFunc::iterator iter = m_mapTimedofunc.find(m_curState);
	if (iter == m_mapTimedofunc.end())
		return;
	(this->*m_mapTimedofunc[m_curState])(m_nID);
}

void SkillBase::OnFly(uint32_t skillId)
{

}

Point3<float> SkillBase::GetSkillDir()
{
	return m_skillDir;
}
void SkillBase::SetSkillDir(Point3<float> dir)
{
	m_skillDir = dir;
}
